mod annotation;
mod rust_highlighter;
mod search_highlighter;
mod syntax_highlighter;
pub use annotation::{AnnotatedStr, Annotation, AnnotationType};
pub use rust_highlighter::RustHighlighter;
pub use search_highlighter::SearchHighlighter;
pub use syntax_highlighter::SyntaxHighlighter;

use crate::{
    editor::{FileType, Line},
    prelude::{LineIdx, Location},
};

// 工厂函数，根据提供的文件类型创建一个语法高亮器
fn create_syntax_highlighter(file_type: FileType) -> Option<Box<dyn SyntaxHighlighter>> {
    match file_type {
        FileType::Rust => Some(Box::<RustHighlighter>::default()),
        FileType::Text => None,
    }
}

#[derive(Default)]
pub struct Highlighter<'a> {
    // 语法高亮器
    syntax_highlighter: Option<Box<dyn SyntaxHighlighter>>,
    // 搜索结果高亮器
    search_result_highlighter: Option<SearchHighlighter<'a>>,
}

impl<'a> Highlighter<'a> {
    pub fn new(
        matched_word: Option<&'a str>,
        selected_match: Option<Location>,
        file_type: FileType,
    ) -> Self {
        let search_result_highlighter =
            matched_word.map(|matched_word| SearchHighlighter::new(matched_word, selected_match));

        Self {
            syntax_highlighter: create_syntax_highlighter(file_type),
            search_result_highlighter,
        }
    }

    // 获取高亮注释，将两个高亮器产生的注释合并到一个Vec中
    pub fn get_annotations(&self, idx: LineIdx) -> Vec<Annotation> {
        let mut result = Vec::new();

        if let Some(syntax_highlighter) = &self.syntax_highlighter {
            if let Some(annotations) = syntax_highlighter.get_annotations(idx) {
                result.extend(annotations.iter().copied());
            }
        }

        if let Some(search_result_highlighter) = &self.search_result_highlighter {
            if let Some(annotations) = search_result_highlighter.get_annotations(idx) {
                result.extend(annotations.iter().copied());
            }
        }

        result
    }

    // 在每个具体的 highlighter 上调用相应的 highlight 函数
    pub fn highlight(&mut self, idx: LineIdx, line: &Line) {
        if let Some(syntax_highlighter) = &mut self.syntax_highlighter {
            syntax_highlighter.highlight(idx, line);
        }

        if let Some(search_result_highlighter) = &mut self.search_result_highlighter {
            search_result_highlighter.highlight(idx, line);
        }
    }
}
